home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / System / XFD / Developer / Sources / C / MMCMP.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-09-16  |  7.2 KB  |  261 lines

  1. /* XFD external slave for MMCMP format by Kyzer/CSG <kyzer@4u.net>
  2.  * Based on code by Olivier Lapicque <olivierl@jps.net>
  3.  * MMCMP format (C) Emmanuel Giasson
  4.  */
  5.  
  6. #include <libraries/xfdmaster.h>
  7. #include <proto/exec.h>
  8. #include <exec/memory.h>
  9. #include "SDI_compiler.h"
  10.  
  11. static char version[]="$VER: MMCMP 1.0 (12.08.2001) by <kyzer@4u.net>";
  12.  
  13. /* header format (little-endian):
  14.  * 0       "ziRC"
  15.  * 4       "ONia"
  16.  * 8       header size.w (always 14)
  17.  * 10      header version.w
  18.  * 12      number of blocks.w
  19.  * 14      unpacked file length.l
  20.  * 18      offset to block offset table.l (usually 24)
  21.  * 22      unknown.b
  22.  * 23      unknown.b
  23.  * 24      SIZEOF
  24.  *
  25.  * block offset table (little endian):
  26.  * 0       offset to block[1].l
  27.  * 4       ...
  28.  * ...     offset to block[number of blocks].l
  29.  *
  30.  *
  31.  * block format (little-endian):
  32.  * 0       unpacked block length.l
  33.  * 4       packed block length.l
  34.  * 8       XOR checksum.l
  35.  * 12      number of sub-blocks.w
  36.  * 14      flags.w
  37.  * 16      tt_entries.w
  38.  * 18      num_bits.w
  39.  * 20      SIZEOF
  40.  *
  41.  * sub-block format (little-endian):
  42.  * 0       sub-block output offset in dest file.l
  43.  * 4       sub-block length.l
  44.  */
  45.  
  46. #define mmcmp_COMP    0x0001
  47. #define mmcmp_DELTA    0x0002
  48. #define mmcmp_16BIT    0x0004
  49. #define mmcmp_STEREO    0x0100
  50. #define mmcmp_ABS16    0x0200
  51. #define mmcmp_ENDIAN    0x0400
  52.  
  53. #define EndGetI32(a)  ((((a)[3])<<24)|(((a)[2])<<16)|(((a)[1])<<8)|((a)[0]))
  54. #define EndGetI16(a)  ((((a)[1])<<8)|((a)[0]))
  55. #define GETLONG(x,n) EndGetI32(&x[n])
  56. #define GETWORD(x,n) EndGetI16(&x[n])
  57.  
  58. #define ERROR(x)  { xbi->xfdbi_Error = XFDERR_##x ; return 0; }
  59.  
  60. const ULONG mmcmp_16bitcmds[16] = {
  61.   0x0001, 0x0003, 0x0007, 0x000F, 0x001E, 0x003C, 0x0078, 0x00F0,
  62.   0x01F0, 0x03F0, 0x07F0, 0x0FF0, 0x1FF0, 0x3FF0, 0x7FF0, 0xFFF0
  63. };
  64. const UBYTE mmcmp_16bitfetch[16] = {
  65.   4, 4, 4, 4, 3, 2, 1, 0,
  66.   0, 0, 0, 0, 0, 0, 0, 0
  67. };
  68. const ULONG mmcmp_8bitcmds[8] = {
  69.   0x01, 0x03, 0x07, 0x0F, 0x1E, 0x3C, 0x78, 0xF8
  70. };
  71. const UBYTE mmcmp_8bitfetch[8] = {
  72.   3, 3, 3, 3, 2, 1, 0, 0
  73. };
  74.  
  75.  
  76. struct bitbuf {
  77.   ULONG buf;
  78.   UBYTE *src, *end;
  79.   int bits;
  80. };
  81.  
  82. ULONG mmcmp_getbits(struct bitbuf *bb, int bits) {
  83.   ULONG out;
  84.   if (!bits) return 0;
  85.   while (bb->bits < 24) {
  86.     bb->buf |= ((bb->src < bb->end) ? *bb->src++ : 0) << bb->bits;
  87.     bb->bits += 8;
  88.   }
  89.   out = bb->buf & ((1<<bits)-1);
  90.   bb->buf >>= bits;
  91.   bb->bits -= bits;
  92.   return out;
  93. }
  94.  
  95.  
  96.  
  97. ASM(BOOL) MMCMP_recog(REG(a0, UBYTE *buf), REG(d0, ULONG length)
  98.   REG(a1, struct xfdRecogResult *rr)) {
  99.   if (strncmp(buf, "ziRCONia", 8) == 0) {
  100.     rr->xfdrr_MinTargetLen = rr->xfdrr_FinalTargetLen = GETLONG(buf, 14);
  101.     return (BOOL) 1;
  102.   }
  103.   return (BOOL) 0;
  104. }
  105.  
  106. ASM(BOOL) MMCMP_decrunch(REG(a0, struct xfdBufferInfo * xbi),
  107.   REG(a6, struct xfdMasterBase *xfdMasterBase)) {
  108.  
  109.   UBYTE *src  = (UBYTE *) xbi->xfdbi_SourceBuffer;
  110.   UBYTE *dest = (UBYTE *) xbi->xfdbi_UserTargetBuf;
  111.   UBYTE *ends = &src[xbi->xfdbi_SourceBufLen];
  112.   UBYTE *endd = &dest[xbi->xfdbi_TargetBufSaveLen];
  113.   UBYTE *inpos, *block, *outp, *endp, *ptable;
  114.  
  115.   int flags, blk, subblk, num_bits, fetch;
  116.   int num_subblocks, num_blocks = GETWORD(src, 12);
  117.   ULONG x, oldx, y, new_bits;
  118.  
  119.   struct bitbuf bb;
  120.  
  121.   for (blk = 0; blk < num_blocks; blk++) {
  122.     /* get block pointer from block offset table */
  123.     block = &src[GETLONG(src, 24 + (blk*4))];
  124.     if ((block + 20) > ends) ERROR(CORRUPTEDDATA);
  125.  
  126.     num_subblocks = GETWORD(block, 12);
  127.     flags = GETWORD(block, 14);
  128.  
  129.     /* point inpos at the start of actual block data
  130.      * (after the block and subblock headers)
  131.      */
  132.     inpos = &block[20 + (8 * num_subblocks)];
  133.     if (inpos > ends) ERROR(CORRUPTEDDATA);
  134.  
  135.     if (flags & mmcmp_COMP) {
  136.       num_bits = GETWORD(block, 18);
  137.       if (num_bits >= ((flags & mmcmp_16BIT) ? 16 : 8)) ERROR(CORRUPTEDDATA);
  138.  
  139.       /* initialise oldx for delta values */
  140.       oldx = 0;
  141.  
  142.       /* initialise bit buffer */
  143.       bb.bits = bb.buf = 0;
  144.       bb.src  = &inpos[GETWORD(block, 16)];
  145.       bb.end  = &inpos[GETLONG(block, 4)];
  146.  
  147.       /* initialise 8-bit lookup table */
  148.       ptable = inpos;
  149.     }
  150.  
  151.     /* decrunch each sub-block */
  152.     for (subblk = 0; subblk < num_subblocks; subblk++) {
  153.  
  154.       /* each sub-block defines an offset in the decrunched file where
  155.        * it should decrunch to, and how long its decrunched length is
  156.        */
  157.       outp = &dest[GETLONG(block, 20 + (subblk*8))];
  158.       endp = &outp[GETLONG(block, 24 + (subblk*8))];
  159.  
  160.       if (endp > endd) ERROR(CORRUPTEDDATA);
  161.  
  162.       if (flags & mmcmp_COMP) {
  163.         if (flags & mmcmp_16BIT) {
  164.           /* 16-bit compression */
  165.           while (outp < endp) {
  166.             x = 0x10000;
  167.             y = mmcmp_getbits(&bb, num_bits+1);
  168.             if (y >= mmcmp_16bitcmds[num_bits]) {
  169.               fetch = mmcmp_16bitfetch[num_bits];
  170.               new_bits = ((y - mmcmp_16bitcmds[num_bits]) << fetch)
  171.                        | mmcmp_getbits(&bb, fetch);
  172.               if (new_bits != num_bits) {
  173.                 num_bits = new_bits & 0x0F;
  174.               }
  175.               else {
  176.                 if ((y = mmcmp_getbits(&bb, 4)) == 0x0F) {
  177.                   if (mmcmp_getbits(&bb, 1) != 0) break;
  178.                   x = 0xFFFF;
  179.                 }
  180.                 else {
  181.                   x = 0xFFF0 + y;
  182.                 }
  183.               }
  184.             }
  185.             else {
  186.               x = y;
  187.             }
  188.  
  189.             if (x < 0x10000) {
  190.               x = (x & 1) ? (0xFFFFFFFF - (x >> 1)) : (x >> 1);
  191.               if (flags & mmcmp_DELTA) {
  192.                 x += oldx;
  193.                 oldx = x;
  194.               }
  195.               else if (!(flags & mmcmp_ABS16)) {
  196.                 x ^= 0x8000;
  197.               }
  198.               /* output 16-bit word, little-endian format */
  199.               *outp++ = (x)      & 0xFF;
  200.               *outp++ = (x >> 8) & 0xFF;
  201.             }
  202.           }
  203.         }
  204.         else {
  205.           /* 8-bit compression */
  206.           while (outp < endp) {
  207.             x = 0x100;
  208.             y = mmcmp_getbits(&bb, num_bits+1);
  209.             if (y >= mmcmp_8bitcmds[num_bits]) {
  210.               fetch = mmcmp_8bitfetch[num_bits];
  211.               new_bits = ((y - mmcmp_8bitcmds[num_bits]) << fetch)
  212.                        | mmcmp_getbits(&bb, fetch);
  213.               if (new_bits != num_bits) {
  214.                 num_bits = new_bits & 0x07;
  215.               }
  216.               else {
  217.                 if ((y = mmcmp_getbits(&bb, 3)) == 0x07) {
  218.                   if (mmcmp_getbits(&bb, 1) == 0) x = 0xFF; else break;
  219.                 }
  220.                 else {
  221.                   x = 0xF8 + y;
  222.                 }
  223.               }
  224.             }
  225.             else {
  226.               x = y;
  227.             }
  228.  
  229.             if (x < 0x100) {
  230.               x = ptable[x];
  231.               if (flags & mmcmp_DELTA) {
  232.                 x += oldx;
  233.                 oldx = x;
  234.               }
  235.               /* output 8-bit byte */
  236.               *outp++ = x & 0xFF;
  237.             }
  238.  
  239.           }
  240.         }
  241.       }
  242.       else {
  243.         /* block is not compressed */
  244.         if ((inpos + (endp-outp)) > ends) ERROR(CORRUPTEDDATA);
  245.         memcpy(outp, inpos, (endp-outp));
  246.         inpos += (endp-outp);
  247.       }
  248.     }
  249.   }
  250.  
  251.   /* good exit */
  252.   return 1;
  253. }
  254.  
  255. struct xfdSlave FirstSlave = {
  256.   NULL, XFDS_VERSION, 39, "(MMCMP) Data Cruncher",
  257.   XFDPFF_DATA|XFDPFF_RECOGLEN|XFDPFF_USERTARGET,
  258.   0, (BOOL (*)()) MMCMP_recog, (BOOL (*)()) MMCMP_decrunch,
  259.   NULL, NULL, 0, 0, 44
  260. };
  261.